package com.example.tcp.server.mqtt;

import com.example.tcp.server.Client;
import com.example.tcp.server.Frame;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.mqtt.*;
import io.netty.util.AsciiString;
import io.netty.util.AttributeKey;
import lombok.Getter;
import lombok.ToString;

import java.util.function.Function;

import static io.netty.handler.codec.mqtt.MqttMessageType.CONNECT;

@Getter
@ToString
public class MqttFrame extends Frame {

    private static final AttributeKey<String> CLIENT_ID = AttributeKey.valueOf("CLIENT_ID");

    private MqttMessage message;
    public MqttFrame(MqttMessage message) {
        super( message.payload() instanceof ByteBuf ? (ByteBuf) message.payload() : Unpooled.EMPTY_BUFFER);
        this.message = message;
    }

    @Override
    public Client getClient(ChannelHandlerContext ctx) {
        MqttMessageType messageType = message.fixedHeader().messageType();
        String clientId = null;
        if(messageType == CONNECT) {
            MqttConnectPayload payload = (MqttConnectPayload)message.payload();
            clientId = payload.clientIdentifier();
            ctx.channel().attr(CLIENT_ID).set(clientId);
        } else {
            if(ctx.channel().hasAttr(CLIENT_ID)) {
                clientId = ctx.channel().attr(CLIENT_ID).get();
            }
        }
        if(clientId != null) {
            AsciiString deviceId = AsciiString.cached(clientId);
            return Client.getOrCreateClient(deviceId, ctx.channel(), new Function<AsciiString, Client>() {
                @Override
                public Client apply(AsciiString key) {
                    return new MqttClient(key, ctx.channel());
                }
            });
        }
        return null;
    }
}
